#ifndef Level_h
#define Level_h

#include <sstream>
#include <string>
#include <list>
#include <windows.h>
#include <vector>

// Includes for using TinyXML
#include "tinystr.h"
#include "tinyxml.h"

#include "cPlayer.h"
#include "LevelRules.h"
#include "../Conversation/ConversationManager.h"

using namespace std;

const string kPathConversation = "./Data/Conversation.xml";
const unsigned int kfMessage_Y = 21;

enum eSpecialCellContent {
	eObject = 0,
	ePlayer,
	eSpecialLocation
};


typedef struct  {
public:
	char mcId;
	int miX;
	int miY;
   char mcSymbol;
   eSpecialCellContent meCellContent;
   string mName;
} cSpecialCell;



// Use of typedef to simplify the sintax
typedef list <cSpecialCell*> cSpecialCellDictionary;
typedef cSpecialCellDictionary::iterator cSpecialCellDictionaryIt;

typedef list<cObject *> cObjectList;
typedef cObjectList::iterator cObjectListIt;

class cLevel {
public:
	// Function to initialize the level
	bool Init(string path);
   // Function to uptade the level
	void Update(float lfTimeStep);
	// Function to render the level
	void Render();
	// Function to deinitialize the level
	bool DeInit();

	// Read the XML
	void ReadLevel(string path);
	// Is wall
	bool IsWall(int luiX, int luiY);
	bool IsInCell(char lParam1, string lParam2 );
	// Find the special cell in the dictionary
	bool LookUp(char lcId,cSpecialCellDictionaryIt &it);
	// Find the Object in the list of objects
	bool LookUp(string lname,cObjectListIt &itObject);
	// Remove a Object of the ObjectList
	void Remove(string lname);
	// Functions for the management of the messages
	inline void SetMessageOn(bool lbIsOn) {mbMessageOn = lbIsOn;}
	inline bool GetMessageOn() {return mbMessageOn;}
	inline void InsertMessage(string lMessage) {mMessage = lMessage;}
	inline string GetMessage(string lMessage) {return mMessage;}
	inline int GetActionsExecuted() {return muiActionsExecuted;}
	inline void IncrementActionsExecuted() {muiActionsExecuted++;}
	inline void ResetActionsExecuted() {muiActionsExecuted = 0;}
	inline cConversationManager &GetConversationManager() {return mConversationManager;}
private:
	
	cConversationManager mConversationManager;
	// Map's dimensions
	int muiWidth;
	int muiHeight;
	// Map
	bool *mabMap;
	// List declaration
	cSpecialCellDictionary mDictionary;
	cObjectList mObjects;
	cLevelRules mRules;
	// We are writting a message
	bool mbMessageOn;
	string mMessage;
	unsigned int muiActionsExecuted;
	
	// Private methods to read the XML
	void ReadMap(stringstream& mapBuffer, TiXmlNode* pParent);
	void ReadSpecialCells(stringstream& cellsBuffer, TiXmlNode* pParent);
	void ReadRules(stringstream& rulesBuffer, TiXmlNode* pChild);
	void ReadConditions(stringstream& condBuffer, TiXmlNode* pChild, cLevelRule& rule);
	void ReadActions(stringstream& actionBuffer, TiXmlNode* pChild, cLevelRule& rule);
	
	void RenderObjects();
	void UpdateObjects(float lfTimeStep);

	int GetSpecialType(string name);

	void inline SetCellContent(cSpecialCellDictionaryIt it, int luiVal) {
		(*it)->meCellContent = (eSpecialCellContent) luiVal;
	}
	void inline SetName(cSpecialCellDictionaryIt it, string lVal) {
		(*it)->mName = lVal;
	}

	void inline SetSymbol(cSpecialCellDictionaryIt it, char lVal) {
		(*it)->mcSymbol = lVal;
	}
	void inline DeleteEntry(cObjectListIt &itObject) {
		delete(*itObject);
		itObject = mObjects.erase(itObject);	
	}

	void InsertObject(const cSpecialCellDictionaryIt it);
	cStatement InsertCondition(string lType, string lCellId, string lObjectName);
	cStatement InsertAction(string lType, vector<string> lParam);
};
#endif